package com.gitee.wsl.common.more.ext.glide

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.widget.ImageView
import androidx.annotation.DrawableRes
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.LazyHeaders
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.target.Target
import com.gitee.wsl.android.ext.ApplicationInit.application
import com.gitee.wsl.android.imageloader.ImageLoadScope
import com.gitee.wsl.android.imageloader.Loader
import com.gitee.wsl.common.more.ext.glide.transform.CornerTransform
import com.gitee.wsl.common.more.ext.glide.transform.PhotoMaskTransformation
import com.gitee.wsl.result.EntryResult
import com.gitee.wsl.result.sample.ValueResult
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import timber.log.Timber
import java.io.File
import java.net.MalformedURLException
import java.net.URL


class GlideImageLoader(val context: Context = application,
                       val glide: RequestManager = Glide.with(context),
                       private val requestOptionsConfig: (RequestOptions.()->Unit)? = null
): Loader {

    /**
     * 返回一个请求的配置
     */
    @SuppressLint("CheckResult")
    private fun getRequestOptions(@DrawableRes resId: Int, isSkipCache: Boolean=false): RequestOptions {
        val options = RequestOptions()
        if (isSkipCache) {
            options.skipMemoryCache(true)
            options.diskCacheStrategy(DiskCacheStrategy.NONE)
        }
        //设置一张占位图
        options.placeholder(resId)
        requestOptionsConfig?.let { it(options) }
        return options
    }

     fun displayImage( url: Uri, simpleTarget: CustomTarget<Bitmap>) {
        try {
            glide.asBitmap().load(url).into(simpleTarget)
        } catch (e: Exception) {
            Timber.d("加载图片出错:" + e.message)
        }
    }

     fun displayImage(
        url: String,
        imageView: ImageView,
        requestOptions: RequestOptions
    ) {
         var url1: URL? = null
         try {
             url1 = URL(url)
         } catch (e: MalformedURLException) {
             e.printStackTrace()
         }
         url1?.let {
             val glideUrl =
                 GlideUrl(it, LazyHeaders.Builder().build())
             Glide.with(imageView.context.applicationContext)
                 .asDrawable()
                 .load(glideUrl)
                 .apply(requestOptions)
                 .into(imageView)
         }
    }


    override fun displayImageRound(url: String, view: ImageView, corner: Int, desId: Int) {
        val options = getRequestOptions(desId).transform(RoundedCorners(corner))
        loadImage( url, view, options)
    }

    override fun displayImageRound(
        url: String,
        view: ImageView,
        desId: Int,
        leftTop: Boolean,
        rightTop: Boolean,
        leftBottom: Boolean,
        rightBottom: Boolean,
        roundRadius: Float
    ) {
        val cornerTransform = CornerTransform(roundRadius)
        cornerTransform.setCorner(leftTop, rightTop, leftBottom, rightBottom)
        val options = RequestOptions().placeholder(desId)
            .transform(cornerTransform)
        displayImage(url, view, options)
    }

    override fun displayImage(url: Uri, view: ImageView, desId: Int) {
        val options = getRequestOptions(desId)
        loadImage(url, view, options)
    }

    override fun displayImage(url: String, view: ImageView, desId: Int, isSkipCache: Boolean) {
        val options = getRequestOptions(desId, isSkipCache)
        loadImage(url, view, options)
    }

    @SuppressLint("CheckResult")
    override fun displayImage(url: String, view: ImageView, height: Int, width: Int, desId: Int) {
        val options = getRequestOptions(desId)
        options.override(width, height)
        loadImage( url, view, options)
    }

    @SuppressLint("CheckResult")
    override fun displayImage(
        url: String,
        view: ImageView,
        height: Int,
        width: Int,
        sizeMultiplier: Float,
        desId: Int
    ) {
        val options = getRequestOptions(desId)
        options.sizeMultiplier(sizeMultiplier)
        options.override(width, height)
        loadImage( url, view, options)
    }

    override fun displayLocalImage(url: String, view: ImageView, desId: Int) {
        val options = getRequestOptions(desId)
        val file = File(url)
        if (file.exists()) {
            loadImage(file, view, options)
        }
    }

    override fun <T> into(url: String, target: T, config: ImageLoadScope.() -> Unit) {
        val imageLoadScope=GlideImageLoadScope(RequestOptions())
        config(imageLoadScope)
        imageLoadScope.requestListener?.let {
            glide.addDefaultRequestListener(it)
        }
        when(target){
            is ImageView->{}
            is CustomTarget<*>->{}
        }
    }

    override fun clearMemory() {
        GlideExt.clearImageMemoryCache(context)
    }

    override fun clearDiskCache() {
        GlideExt.clearImageDiskCache()
    }

    override fun trimMemory(level: Int) {
        glide.onTrimMemory(level)
    }

    override fun clearAllMemoryCaches() {
        glide.onLowMemory()
    }

    override fun resumeRequest() {
        glide.resumeRequests()
    }

    override fun pauseRequest() {
       glide.pauseRequests()
    }

    private fun loadImage( url: Any, view: ImageView, options: RequestOptions) {
        try {
            if (url is String) {
                displayImage(url, view, options)
            } else {
                Glide.with(context).load(url).apply(options).into(view)
            }
        } catch (e: Exception) {
            Timber.e("加载图片出错：" + e.message)
        }
    }
}

class GlideImageLoadScope(val requestOptions: RequestOptions):ImageLoadScope{
   var requestListener: RequestListener<Any>?=null

    override fun getBaseScope(): Any {
        return requestOptions
    }

    @SuppressLint("CheckResult")
    override fun targetSize(width: Int, height: Int) {
        requestOptions.override(width, height)
    }

    @SuppressLint("CheckResult")
    override fun maskColor(maskColor: Int) {
        requestOptions.transform(PhotoMaskTransformation(maskColor))
    }

    override fun roundAngle(angle: Float) {
        TODO("Not yet implemented")
    }

    @SuppressLint("CheckResult")
    override fun circleCrop() {
        requestOptions.circleCrop()
    }

    @SuppressLint("CheckResult")
    override fun asGif(getGifDrawable: Boolean) {
        requestOptions.dontAnimate()
    }

    @SuppressLint("CheckResult")
    override fun centerCrop() {
        requestOptions.centerCrop()
    }

    @SuppressLint("CheckResult")
    override fun centerInside() {
        requestOptions.centerInside()
    }

    @SuppressLint("CheckResult")
    override fun fitCenter() {
        requestOptions.fitCenter()
    }

    @SuppressLint("CheckResult")
    override fun skipLocalCache() {
        requestOptions.diskCacheStrategy(DiskCacheStrategy.NONE)
    }

    @SuppressLint("CheckResult")
    override fun skipNetCache() {
        TODO("Not yet implemented")
    }

    override fun skipOverride(skip: Boolean) {
        TODO("Not yet implemented")
    }

    @SuppressLint("CheckResult")
    override fun skipMemoryCache() {
        requestOptions.skipMemoryCache(true)
    }

    @SuppressLint("CheckResult")
    override fun placeholder(placeholder: Int) {
        requestOptions.placeholder(placeholder)
    }

    @SuppressLint("CheckResult")
    override fun placeholder(placeholder: Drawable) {
       requestOptions.placeholder(placeholder)
    }

    @SuppressLint("CheckResult")
    override fun error(resId: Int) {
        requestOptions.error(resId)
    }

    @SuppressLint("CheckResult")
    override fun error(drawable: Drawable) {
        requestOptions.error(drawable)
    }

    override fun loadState(): Flow<EntryResult<Any, Any>> = callbackFlow{
        requestListener = object:RequestListener<Any>{
            override fun onLoadFailed(
                e: GlideException?,
                model: Any?,
                target: Target<Any>?,
                isFirstResource: Boolean
            ): Boolean {
                e?.let {
                    trySend(ValueResult.Err(e))
                }
                return false
            }

            override fun onResourceReady(
                resource: Any?,
                model: Any?,
                target: Target<Any>?,
                dataSource: DataSource?,
                isFirstResource: Boolean
            ): Boolean {
                resource?.let {
                    trySend(ValueResult.Ok(it))
                }
                return false
            }
          }
    }

}

/*@SuppressLint("CheckResult")
fun GlideImageLoadScope.asWebp( wrapped:Transformation<Bitmap>){
    requestOptions.optionalTransform(
        WebpDrawable::class.java,
        WebpDrawableTransformation(wrapped)
    )
}*/

